package com.pangus.toolkits.files.download;

import com.pangus.toolkits.files.model.FileInfo;
import lombok.EqualsAndHashCode;

import java.io.*;
import java.util.ArrayList;

/**
 * 分片下载使用
 *
 * @author yingheng chen
 * @description
 * @date 2019/12/5
 */
@EqualsAndHashCode
class DownloadCheckPoint implements Serializable {
    String magic; // magic
    int hashcode; // the hashcode of checkpoint data.
    String downloadFile; // local path for the download.
    ObjectStat objectStat; // object state
    ArrayList<DownloadPart> downloadParts; // download parts list.

    private static final long serialVersionUID = 4682293344365787077L;
    static final String DOWNLOAD_MAGIC = "92611BED-89E2-46B6-89E5-72F273D4B0A3";

    /**
     * Loads the checkpoint data from the checkpoint file.
     */
    public synchronized void load(File cpFile) throws IOException, ClassNotFoundException {
        FileInputStream fileIn = new FileInputStream(cpFile);
        ObjectInputStream in = new ObjectInputStream(fileIn);
        DownloadCheckPoint dcp = (DownloadCheckPoint) in.readObject();
        assign(dcp);
        in.close();
        fileIn.close();
    }

    /**
     * Writes the checkpoint data to the checkpoint file.
     */
    public synchronized void dump(File cpFile) throws IOException {
        this.hashcode = hashCode();
        FileOutputStream fileOut = new FileOutputStream(cpFile);
        ObjectOutputStream outStream = new ObjectOutputStream(fileOut);
        outStream.writeObject(this);
        outStream.close();
        fileOut.close();
    }

    /**
     * Updates the part's download status.
     *
     * @throws IOException
     */
    public synchronized void update(int index, boolean completed) throws IOException {
        downloadParts.get(index).isCompleted = completed;
    }

    /**
     * Check if the object matches the checkpoint information.
     */
    public synchronized boolean isValid(FileInfo meta) {

        if (this.magic == null || !this.magic.equals(DOWNLOAD_MAGIC) || this.hashcode != hashCode()) {
            return false;
        }
        if (this.objectStat.size != meta.getSize() || !this.objectStat.lastModified.equals(meta.getLastModified())) {
            return false;
        }
        return true;
    }


    private void assign(DownloadCheckPoint dcp) {
        this.magic = dcp.magic;
        this.hashcode = dcp.hashcode;
        this.downloadFile = dcp.downloadFile;
        this.objectStat = dcp.objectStat;
        this.downloadParts = dcp.downloadParts;
    }
}
